import Draw from "./draw";
import ToolEvent from "./event";
import ToolReg from "./reg";

class FuncTool {
  draw: Draw;
  event: ToolEvent;
  reg: ToolReg;
  options: Options | undefined;

  constructor(options: Options) {
    this.options = options;

    this.event = new ToolEvent(this.options);
    this.event.init();

    this.draw = new Draw(
      this.event.canvas!,
      this.options.limits,
      this.options.colors
    );
    this.reg = new ToolReg(this.event.express!);

    this.draw.drawAll();
    this.bindEvents();
  }

  isDataLegal(express: string, xstart: number, xend: number): boolean {
    if (express.trim() === "" || isNaN(xstart) || isNaN(xend)) {
      return false;
    }
    if (xstart > xend) {
      return false;
    }
    return true;
  }

  moveEvent(tmpOffsetX: number, tmpOffsetY: number, e: MouseEvent) {
    if (tmpOffsetX < e.offsetX) {
      this.draw.moveTimes.level--;
      this.draw.initAxis(-this.draw.offsetX, 0);
    } else if (tmpOffsetX > e.offsetX) {
      this.draw.moveTimes.level++;
      this.draw.initAxis(this.draw.offsetX, 0);
    }
    if (tmpOffsetY < e.offsetY) {
      this.draw.moveTimes.vertical--;
      this.draw.initAxis(0, -this.draw.offsetY);
    } else if (tmpOffsetY > e.offsetY) {
      this.draw.moveTimes.vertical++;
      this.draw.initAxis(0, this.draw.offsetY);
    }

    this.draw.clear();
    this.draw.drawAll();
  }

  bindEvents() {
    this.event.canvas!.addEventListener("mousedown", (e) => {
      let tmpOffsetX = e.offsetX;
      let tmpOffsetY = e.offsetY;
      const bindMouseEvent = this.moveEvent.bind(this, tmpOffsetX, tmpOffsetY);

      this.event.canvas!.addEventListener("mousemove", bindMouseEvent);
      this.event.canvas!.addEventListener("mouseup", () => {
        this.event.canvas!.removeEventListener("mousemove", bindMouseEvent);
      });
    });

    this.event.draw!.addEventListener("click", () => {
      let express = this.event.express!.value;
      let xstart = Number(this.event.xstart!.value);
      let xend = Number(this.event.xend!.value);

      if (!this.isDataLegal(express, xstart, xend)) {
        return;
      }

      this.draw.funcXStart = xstart;
      this.draw.funcXEnd = xend;
      this.draw.express = this.reg.check();
      this.draw.clear();
      this.draw.drawAll();
    });

    document.addEventListener("mousewheel", (e: Event) => {
      if (
        e.pageX < this.event.root!.offsetLeft ||
        e.pageX > this.draw.el.width
      ) {
        return;
      }
      if (
        e.pageY < this.event.root!.offsetTop ||
        e.pageY > this.draw.el.height
      ) {
        return;
      }
      if (e.deltaY > 0) {
        this.draw.clear();
        this.draw.zoomIn();
        this.draw.drawAll();
      } else {
        this.draw.clear();
        this.draw.zoomOut();
        this.draw.drawAll();
      }
    });

    this.event.backAxis!.addEventListener("click", () => {
      this.draw.backAxis();
    });

    this.event.zoomIn!.addEventListener("click", () => {
      this.draw.clear();
      this.draw.zoomIn();
      this.draw.drawAll();
    });

    this.event.zoomOut!.addEventListener("click", () => {
      this.draw.clear();
      this.draw.zoomOut();
      this.draw.drawAll();
    });
  }
}

export default FuncTool;
